package wangxiaotao.aop;

import lombok.RequiredArgsConstructor;
import lombok.extern.slf4j.Slf4j;
import org.aspectj.lang.ProceedingJoinPoint;
import org.aspectj.lang.annotation.Around;
import org.aspectj.lang.annotation.Aspect;
import org.aspectj.lang.annotation.Pointcut;
import org.aspectj.lang.reflect.MethodSignature;
import org.springframework.stereotype.Component;
import org.springframework.web.context.request.RequestContextHolder;
import org.springframework.web.context.request.ServletRequestAttributes;
import wangxiaotao.aop.annotation.Log;
import wangxiaotao.entity.Logs;
import wangxiaotao.service.LogServer;

import javax.servlet.http.HttpServletRequest;
import java.lang.reflect.Method;
import java.time.LocalDateTime;
import java.util.Arrays;

/**
 * 日志记录切面类
 */
@Component
@Aspect //切面
@Slf4j
@RequiredArgsConstructor
public class LogAspect {
    //注入日志操作server
    private final LogServer logServer;

    //设置切入点表达式
    @Pointcut("@annotation(wangxiaotao.aop.annotation.Log)")
    public void pt(){}

    //环绕通知
    @Around("pt()")
    public Object aroundLog(ProceedingJoinPoint joinPoint) throws Throwable {
        long startTime = System.currentTimeMillis();
        //执行方法
        Object result = joinPoint.proceed();
        long time = System.currentTimeMillis() -  startTime;
        //保存日志操作
        recordLog(joinPoint,time);
        return  result;

    }

    /**
     * 保存日志
     * @param joinPoint
     * @param time
     */
    private void recordLog(ProceedingJoinPoint joinPoint,long time){
        ServletRequestAttributes requestAttributes = (ServletRequestAttributes) RequestContextHolder.getRequestAttributes();
        //获取request
        HttpServletRequest request = requestAttributes.getRequest();
        MethodSignature signature = (MethodSignature)joinPoint.getSignature();
        //获取当前操作方法
        Method method = signature.getMethod();
        //获取方法上@log注解
        Log annotation = method.getAnnotation(Log.class);
        //没有注解直接返回
        if (annotation==null){
            return;
        }
        //有@log注解执行记录日志的操作
        log.debug("========================日志记录开始================================");
        //建立日志类
        Logs logs = new Logs();
        //获取控制器名称
        String controllerName = joinPoint.getTarget().getClass().getSimpleName().replace("Controller","");
        //获取方法名称
        String methodName = signature.getName();
        //日志类数据封装
        logs.setModule(controllerName)
                .setMethod(methodName)
                .setRequestMethod(request.getMethod())
                .setRequestUrl(request.getRemoteAddr()+":"+request.getServerPort()+request.getRequestURI())
                .setRequestParam(Arrays.toString(joinPoint.getArgs()))
                .setOperatorTime(LocalDateTime.now())
                .setRequestTime(time)
                .setOperator((String) request.getSession().getAttribute("username"));
        //保存日志数据
        logServer.save(logs);
        //请求参数
        log.debug("========================日志记录结束================================");
    }
}
